package com.sk.bilibili.tool;

import com.sk.bilibili.generate.info.ClassInfo;
import com.sk.bilibili.generate.info.FieldInfo;
import com.sk.bilibili.generate.utils.Tool;
import lombok.SneakyThrows;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import javax.swing.*;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.OutputStream;
import java.io.StringWriter;
import java.sql.*;
import java.util.Collections;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @author 邵康
 * @date 2021/11/22 17:53
 */
public class GenerateClass {

    //  有  文件 对象  使用表单  没有使用 json
    private static final String URL = "jdbc:mysql://localhost:3306/bilibili3?serverTimezone=GMT%2B8";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "123456";
    private static final String SQL_PATTERN = "SHOW FULL COLUMNS FROM %s";
    private static final Set<String> FILL_FIELD_NAME = Collections.singleton("createDate");
    private static final Boolean CREATE_XML = true;
    private static final String BASE_PATH = "E:/IDEA/BiliBiliWeb/src/main/java/com/sk/bilibili/";
    private static final String[] OUTPUT_PATH = {
            "bean/%s.java",
            "controller/%sController.java",
            "mapper/%sMapper.java",
            "service/%sService.java"};
    private static final String XML_PATH = "E:/IDEA/BiliBiliWeb/src/main/resources/mapper/%sMapper.xml";
    private static final String[] TEMPLATES = {"template/bean.vm", "template/controller.vm","template/mapper.vm","template/service.vm"};
    private static final String XML_TEMPLATE="template/xml.vm";

    public static void main(String[] args) {
        String table = JOptionPane.showInputDialog(null, "请输入要处理的数据表");
        if (table == null || table.equals("")) return;
        generateClass(table);
    }

    @SneakyThrows
    private static void generateClass(String table) {
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(String.format(SQL_PATTERN, table));
        ClassInfo classInfo = new ClassInfo(table);
        handleRes(resultSet, classInfo);
        writeClass(classInfo);
        resultSet.close();
        connection.close();
    }

    @SneakyThrows
    private static void writeClass(ClassInfo classInfo) {
        VelocityEngine ve = new VelocityEngine();
        ve.setProperty("resource.loader", "class");
        ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        ve.init();
        VelocityContext ctx = new VelocityContext();
        Tool tool = new Tool();
        ctx.put("classInfo", classInfo);
        ctx.put("tool",tool);
        String name=tool.upperFirst(classInfo.getName());
        for (int i = 0; i < TEMPLATES.length; i++) {
            Template template = ve.getTemplate(TEMPLATES[i], "utf-8");
            FileWriter writer = new FileWriter(BASE_PATH + String.format(OUTPUT_PATH[i],name));
            template.merge(ctx, writer);
            writer.close();
        }
        if(!CREATE_XML)return;
        Template template = ve.getTemplate(XML_TEMPLATE, "utf-8");
        FileWriter writer = new FileWriter(String.format(XML_PATH,name));
        template.merge(ctx, writer);
        writer.close();
    }

    @SneakyThrows
    private static void handleRes(ResultSet resultSet, ClassInfo classInfo) {
        while (resultSet.next()) {
            FieldInfo info = new FieldInfo(resultSet.getString(1),
                    resultSet.getString(9), transitionType(resultSet.getString(2)));
            info.setPrimaryKey(!resultSet.getString(5).equals(""));
            info.setFill(FILL_FIELD_NAME.contains(info.getName()));
            classInfo.addFieldInfo(info);
        }
    }

    private static String transitionType(String type) {
        switch (type.substring(0, 3)) {
            case "int":
                return "Integer";
            case "var":
                return "String";
            case "big":
                return "Long";
            case "bit":
                return "Boolean";
            case "flo":
                return "Float";
            case "dat":
                return "Date";
            default:
                throw new RuntimeException("无法解析类型" + type);
        }
    }

}
